#!/usr/bin/ruby -KU
#
#   
#     kanatest.rb - Tests for Kanabuche
#
#  Copyright (c) 2007, Alex Marandon
#  All rights reserved.
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions are met:
#  
#    * Redistributions of source code must retain the above copyright notice,
#      this list of conditions and the following disclaimer.
#    * Redistributions in binary form must reproduce the above copyright notice,
#      this list of conditions and the following disclaimer in the documentation
#      and/or other materials provided with the distribution.
#    * Neither the name of newsbiff nor the names of its contributors
#      may be used to endorse or promote products derived from this software 
#      without specific prior written permission.
#  
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
#  POSSIBILITY OF SUCH DAMAGE.

require 'test/unit'
require 'kanabuche'

class ExerciseTester
  attr_reader :success
  def initialize(test_data)
    @test_data = test_data
  end
  def puts(s = "")
    if s =~ /(Hiragana|Katakana|Kanji): (.+)/
      @current_kana = $2
    end
  end
  def gets
    @test_data[@current_kana]
  end
end

class Kanatest < Test::Unit::TestCase

    def testHiraganaBase
        base = KanaBase.new "Hiragana"
        assert_equal "ke", base.romaji("け")
        assert_equal "pyo", base.romaji("ぴょ")
        assert_equal "け", base.kana("ke")
        assert_equal "ぴょ", base.kana("pyo")
        assert_equal "ke", base.romaji(base.kana("ke"))
        assert_equal "ぴょ", base.kana(base.romaji("ぴょ"))
        assert_equal nil, base.kana("qwerty")
        assert_equal nil, base.romaji("qwerty")
        assert_equal "ri", base.kana_word_to_romaji("り")
        assert_equal "e", base.kana_word_to_romaji("え")
        assert_equal "rie", base.kana_word_to_romaji("りえ")
        assert_equal "kodomo", base.kana_word_to_romaji("こども")
        base.randomize!
        base.each { |k| 
            assert_equal k.west_equiv, base.romaji(base.kana(k.west_equiv))
        }
    end

    def testKatakanaBase
        base = KanaBase.new "Katakana"
        assert_equal "ke", base.romaji("ケ")
        assert_equal "pyo", base.romaji("ピョ")
        assert_equal "ケ", base.kana("ke")
        assert_equal "ピョ", base.kana("pyo")
        assert_equal "ke", base.romaji(base.kana("ke"))
        assert_equal "ピョ", base.kana(base.romaji("ピョ"))
        assert_equal nil, base.kana("qwerty")
        assert_equal nil, base.romaji("qwerty")
        assert_equal "ri", base.kana_word_to_romaji("リ")
        assert_equal "e", base.kana_word_to_romaji("エ")
        assert_equal "rie", base.kana_word_to_romaji("リエ")
        assert_equal "kodomo", base.kana_word_to_romaji("コドモ")
        base.randomize!
        base.each { |k| 
            assert_equal k.west_equiv, base.romaji(base.kana(k.west_equiv))
        }
    end

    def testHiraganaExercise
      bases = [KanaBase.new("Hiragana"), ]
      exerciseTester = ExerciseTester.new "か" => "ka", "き" => "ki", 
                              "く" => "ku", "け" => "ke", "こ" => "kX"
      exercise = Exercise.new(bases, ["k"], exerciseTester.method(:gets), 
                              exerciseTester.method(:puts))
      exercise.run
      assert !exerciseTester.success
      assert_equal 5, exercise.length
      assert_equal 4, exercise.success_nb
    end

    def testKatakanaExercise
      bases = [KanaBase.new("Katakana"), ]
      exerciseTester = ExerciseTester.new "カ" => "ka",
      "キ" => "ki",
      "ク" => "ku",
      "ケ" => "ke",
      "コ" => "ko",
      "ラ" => "ra",
      "リ" => "Wi",
      "ル" => "ru",
      "レ" => "re",
      "ロ" => "ro",
      "ア" => "a",
      "イ" => "i",
      "ウ" => "X",
      "エ" => "e",
      "オ" => "o",
      "ナ" => "nY",
      "ニ" => "ni",
      "ヌ" => "nu",
      "ネ" => "nZ",
      "ノ" => "no"
      exercise = Exercise.new(bases, ["k", "", "r", "n"], 
                              exerciseTester.method(:gets), 
                              exerciseTester.method(:puts))
      assert_equal 20, exercise.length
      exercise.run
      assert !exerciseTester.success
      assert_equal 16, exercise.success_nb
    end

    def testMixedExercise
      20.times do
        bases = [KanaBase.new("Katakana"), 
          KanaBase.new("Hiragana")]
        exerciseTester = ExerciseTester.new "カ" => "kX",
          "キ" => "ki",
          "ク" => "ku",
          "ケ" => "ke",
          "コ" => "ko",
          "か" => "Xa",
          "き" => "ki",
          "く" => "ku",
          "け" => "ke",
          "こ" => "ko"
        exercise = Exercise.new(bases, ["k"], 
                              exerciseTester.method(:gets), 
                              exerciseTester.method(:puts))
        exercise.run
        assert !exerciseTester.success
        assert_equal 10, exercise.length
        assert_equal 8, exercise.success_nb
      end
    end

    def testNumbersExercise
      bases = [NumbersBase.new, ]
      answers = NumbersBase::NUMBERS.clone
      answers["三"] = "3XX"
      answers["八"] = "8XX"
      answers["万"] = "10000XX"
      exerciseTester = ExerciseTester.new(answers)
      exercise = Exercise.new(bases, [], 
                            exerciseTester.method(:gets), 
                            exerciseTester.method(:puts))
      exercise.run
      assert !exerciseTester.success
      assert_equal 13, exercise.length
      assert_equal 10, exercise.success_nb
    end
end
